﻿using EnetaMvc.ApplicationServices;
using EnetaMvc.ApplicationServices.Dto;
using EnetaMvc.Web.Attributes;
using EnetaMvc.Web.Extensions;
using EnetaMvc.Web.Models;
using System;
using System.Web.Mvc;

namespace EnetaMvc.Web.Controllers
{
    public class EventsController : BaseController
    {
        private readonly IContentService _contentService;
        private readonly IEventService _eventService;
        private readonly IUserService _userService;

        public EventsController(IContentService contentService, IEventService eventService, IUserService userService)
        {
            _contentService = contentService;
            _eventService = eventService;
            _userService = userService;
        }

        [HttpGet]
        public ActionResult Index(int page = 1)
        {
            var model = new EventListModel();

            if (!User.IsInRole("Administrator"))
                model.Events = _eventService.ListPublicEvents(page, 10);
            else
                model.Events = _eventService.ListAllEvents(page, 10);

            if (Session["UserId"] != null)
            {
                var userId = int.Parse(Session["UserId"].ToString());
                model.Attendings = _eventService.GetUserAttendings(userId);
            }

            return View(model);
        }
        
        [HttpGet]
        public ActionResult Details(long id)
        {
            var evt = _eventService.GetEventById(id);
            if (evt == null)
            {
                return HttpNotFound("Cannot find event with ID " + id);
            }
            
            return View(evt);
        }

        [HttpGet]
        [EnetaAuthorize(Roles = "Administrator")]
        public ActionResult Create()
        {
            var evt = new EventDto();
            return View("Edit", evt);
        }

        [HttpPost]
        [EnetaAuthorize(Roles = "Administrator")]
        public ActionResult Create(EventDto model)
        {
            return SaveEvent(model, null);
        }

        [HttpGet]
        [EnetaAuthorize(Roles = "Administrator")]
        public ActionResult Edit(long id)
        {
            var evt = _eventService.GetEventById(id);
            if (evt == null)
                return HttpNotFound("Cannot find event with id " + id);

            return View(evt);
        }

        [HttpPost]
        [EnetaAuthorize(Roles = "Administrator")]
        [ValidateInput(false)]
        public ActionResult Edit(EventDto model, long[] audienceIds)
        {
            return SaveEvent(model, audienceIds);
        }

        [EnetaAuthorize(Roles="User, Administrator")]
        public ActionResult RegisterToEvent(long id, bool realEvent)
        {
            if (Session["UserId"] == null)
            {
                return Redirect("/login/");
            }
            var userId = (long)Session["UserId"];

            _eventService.RegisterUserToEvent(id, userId, realEvent);

            if (Request.UrlReferrer != null)
                return Redirect(Request.UrlReferrer.AbsoluteUri);

            return RedirectToAction("Details", new { id = id });
        }

        [EnetaAuthorize(Roles = "User, Administrator")]
        public ActionResult UnregisterFromEvent(long id)
        {
            if (Session["UserId"] == null)
            {
                return Redirect("/login/");
            }
            var userId = (long)Session["UserId"];

            _eventService.UnregisterFromEvent(id, userId);

            if (Request.UrlReferrer != null)
                return Redirect(Request.UrlReferrer.AbsoluteUri);

            return RedirectToAction("Details", new { id = id });
        }

        [HttpPost]
        [EnetaAuthorize(Roles = "User, Administrator")]
        public ActionResult AddComment(long id, string body)
        {
            var user = _userService.GetUserByToken(User.Identity.Name);
            var comment = new CommentDto();
            comment.ContentItemId = id;
            comment.Created = DateTime.Now;
            comment.AuthorId = user.Id;
            comment.Body = body;

            _contentService.SaveComment(comment);

            return RedirectToAction("Details", new { id = id });
        }

        public ActionResult vCard(long id)
        {
            var evt = _eventService.GetEventById(id);
            if (evt == null)
                return HttpNotFound("Cannot find event with ID " + id);

            return new vCalActionResult(evt);
        }

        [EnetaAuthorize(Roles = "Administrator")]
        public ActionResult ContentAction(long id, string actionName, long[] tags, string comment = "")
        {
            if (actionName == Resources.EnetaMvc.Edit)
            {
                return RedirectToAction("Edit", new { id = id });
            }

            var user = _userService.GetUserByToken(User.Identity.Name);
            var evt = _eventService.GetEventById(id);
            evt.SaveTagIds = tags;

            if (actionName == Resources.EnetaMvc.Approve)
            {
                if (evt.PublishStateId != 1)
                {
                    evt.PublishStateId = 1;
                    evt.PublishStateById = user.Id;
                    evt.PublishStateDate = DateTime.Now;
                    _contentService.SaveContentItemSlagLog(evt.Id, evt.PublishStateId, evt.PublishStateById);
                }
            }
            if (actionName == Resources.EnetaMvc.Reject)
            {
                if (evt.PublishStateId != 3)
                {
                    evt.PublishStateId = 3;
                    evt.PublishStateById = user.Id;
                    evt.PublishStateDate = DateTime.Now;
                    evt.PublishComment = comment;
                    _contentService.SaveContentItemSlagLog(evt.Id, evt.PublishStateId, evt.PublishStateById);
                }
            }
            _eventService.SaveEvent(evt);

            return RedirectToAction("Details", new { id = id });
        }

        [HttpGet]
        [EnetaAuthorize(Roles = "Administrator")]
        public ActionResult Delete(long id)
        {
            var evt = _eventService.GetEventById(id);
            if (evt == null)
                return HttpNotFound("Cannot find event " + id);

            return View(evt);
        }

        [HttpPost]
        [EnetaAuthorize(Roles = "Administrator")]
        public ActionResult DeleteConfirmed(long id)
        {
            _eventService.DeleteEvent(id);

            return RedirectToAction("Index");
        }

        [NonAction]
        private ActionResult SaveEvent(EventDto model, long[] audienceIds)
        {
            if (!ModelState.IsValid)
                return View("Edit", model);

            if (model.Id == 0)
            {
                model.CreatedById = Session.GetUserId();
                model.PublishStateById = Session.GetUserId();
            }

            model.SaveAudienceIds = audienceIds;

            _eventService.SaveEvent(model);

            return RedirectToAction("Index");
        }
    }
}
